using System;
using System.Text;
using System.Xml;
using System.Collections;
using System.Configuration;

namespace DotNetScriptEngine
{
	/// <summary>
	/// Summary description for CodeStruct.
	/// </summary>
	internal class Script : ATrace
	{		
		/// <summary>
		/// Use the constructor to load the global settings from the config file,
		/// as well as parse out the dnml script file for any settings and the code
		/// </summary>		
		internal Script(string sourceFromFile)
		{								
			try
			{
				references = new ArrayList();
				userPreferences = new UserPreferences();

				//load any default user preferences from app.config file
				LoadDefaultSettingsFromConfig();
			}
			catch(System.Exception ex)
			{
				throw new Exception("Error: An exception occurred while loading xml config file data", ex);
			}

			XmlTextReader xml = null;

			try
			{
				//Load the dnml file and parse it
				XmlParserContext context = new XmlParserContext(null, null, null, XmlSpace.None);
				xml = new XmlTextReader(sourceFromFile, XmlNodeType.Element, context);			

				while (xml.Read())
				{
					//pull out any assembly references
					if (xml.Name == "reference")
						References.Add(xml.GetAttribute("assembly"));
					
					//get the language the script is written in
					else if (xml.Name == "language")
					{
						//Check to see what language the script is written in
						userPreferences.defaultLanguage = xml.GetAttribute("name");
	
						//Get the entry point into the generated assembly
						if (xml.AttributeCount == 2)
						{							
							string entryFunction = xml.GetAttribute("entryPoint");
							if (entryFunction.Length > 0)
								userPreferences.entryPoint = entryFunction;
						}
					}

						//should console window remain open after script is run
					else if (xml.Name == "waitForUserAction")
						userPreferences.waitForUserAction = bool.Parse(xml.GetAttribute("value"));

						//pull out the code
					else if (xml.Name == "scriptCode")
						sourceCode = xml.ReadElementString("scriptCode").Trim();						
				}				
			}
			catch (Exception ex)
			{
				OnTrace ("Error: An exception occurred while parsing the script block", ex);				
			}
			finally
			{
				if (xml != null)
					xml.Close();
			}
		}		

		private void LoadDefaultSettingsFromConfig()
		{	
			//Load all assembly references
			references.AddRange((ArrayList)ConfigurationSettings.GetConfig("referencedAssemblies/assembly"));

			//Load all supported extra languages			
			languages = (Hashtable)ConfigurationSettings.GetConfig("supportedLanguages/language");

			//Pre init language info for C# and VB
			languages.Add("C#", new DotNetLanguage("C#", "", ""));
			languages.Add("VB", new DotNetLanguage("VB", "", ""));
			
			//Load user script engine preferences
			userPreferences = (UserPreferences)ConfigurationSettings.GetConfig("userPreferences");						
		}				

		private UserPreferences userPreferences;

		//Holds the main source code that will be dynamically compiled and executed
		private string sourceCode;
		internal string SourceCode
		{
			get{return sourceCode;}
		}
		
		//Holds the method name that will act as the assembly entry point		
		internal string EntryPoint
		{
			get{return userPreferences.entryPoint;}
		}

		//A flag the determines if console window should remain open until user clicks enter			
		internal bool WaitForUserAction
		{
			get{return userPreferences.waitForUserAction;}
		}

		//A list of all assemblies that are referenced by the created assembly
		private ArrayList references;	
		internal ArrayList References
		{
			get{return references;}
		}

		//A list of all languages that are referenced by the created assembly
		private Hashtable languages;	
		internal DotNetLanguage Language
		{
			get{return (DotNetLanguage)languages[userPreferences.defaultLanguage];}
		}			
	}
}